//! Connection management utilities

use std::net::TcpStream as StdTcpStream;
use tokio::net::TcpStream;
use std::time::Duration;

/// Connection configuration
#[derive(Debug, Clone)]
pub struct ConnectionConfig {
    /// Connection timeout
    pub timeout: Duration,
    /// Keep-alive timeout
    pub keep_alive: Duration,
}

impl Default for ConnectionConfig {
    fn default() -> Self {
        Self {
            timeout: Duration::from_secs(30),
            keep_alive: Duration::from_secs(60),
        }
    }
}

impl ConnectionConfig {
    /// Create a new connection configuration with custom timeouts
    pub fn new(timeout: Duration, keep_alive: Duration) -> Self {
        Self { timeout, keep_alive }
    }

    /// Create a connection configuration with default timeouts
    pub fn default_config() -> Self {
        Self::default()
    }
}

/// Connection utilities
pub struct Connection;

impl Connection {
    /// Create a new TCP connection with timeout
    pub async fn connect_with_timeout(addr: &str, timeout: Duration) -> std::io::Result<TcpStream> {
        let std_stream = StdTcpStream::connect_timeout(
            &addr.parse().map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?,
            timeout,
        )?;
        
        std_stream.set_nonblocking(true)?;
        TcpStream::from_std(std_stream)
    }

    /// Check if a connection is still alive
    pub async fn is_alive(stream: &mut TcpStream) -> bool {
        use tokio::io::Interest;
        
        match stream.ready(Interest::READABLE | Interest::WRITABLE).await {
            Ok(ready) => ready.is_readable() && ready.is_writable(),
            Err(_) => false,
        }
    }

    /// Get peer address from connection
    pub fn peer_addr(stream: &TcpStream) -> Option<String> {
        stream.peer_addr().ok().map(|addr| addr.to_string())
    }

    /// Get local address from connection
    pub fn local_addr(stream: &TcpStream) -> Option<String> {
        stream.local_addr().ok().map(|addr| addr.to_string())
    }
}